// Scene Manager
// (c) jimon game studio

#ifndef JEH_CSCENEMANAGER
#define JEH_CSCENEMANAGER

#include "ISceneManager.h"
#include "jeRenderPassGroupQueue.h"

namespace je
{
	namespace scene
	{
		//! Scene Manager
		class CSceneManager:public je::scene::ISceneManager
		{
		protected:
			//! Current Render
			video::IRender * CurrentRender;

			//! Root
			ISceneNode * Root;

			//! Compositor List
			CompositorListType * CompositorList;

			//! Previous Compositor
			ICompositor * PreviousCompositor;

			//! Node Factory
			NodeFactoryType * NodeFactory;

			//! Animator Factory
			AnimatorFactoryType * AnimatorFactory;

			//! Compositor Factory
			CompositorFactoryType * CompositorFactory;

			//! Current Camera
			ICameraSceneNode * CurrentCamera;

			//! Current Layer Control
			u1 CurrentLayerControl;

			//! Pass Groups List
			jeRenderPassGroupQueue * PassGroups[RPG_MAX];

			//! Light List
			LightListType * LightList;
			
			//! Swap Layers
			void SwapLayers(ISceneNode * Node,s32 Layer1,s32 Layer2);
		public:
			//! Constructor
			CSceneManager(video::IRender * Render,BaseSceneManagerCompositors CompositorType);

			//! Destructor
			~CSceneManager();

			//! Create Camera Scene Node
			ICameraSceneNode * CreateCamera(ISceneNode * Parent);

			//! Create Sprite Scene Node
			ISpriteSceneNode * CreateSprite(ISceneNode * Parent);

			//! Create Pivot Scene Node
			ISceneNode * CreatePivot(ISceneNode * Parent);

			//! Create Debug Scene Node
			IDebugSceneNode * CreateDebug(ISceneNode * Parent = NULL);

			//! Create Text Scene Node
			ITextSceneNode * CreateText(const jeStringd & Text,ISceneNode * Parent);

			//! Create Mesh Scene Node
			IMeshSceneNode * CreateMeshNode(ISceneNode * Parent = NULL);
			
			//! Create Light Scene Node
			ILightSceneNode * CreateLight(ISceneNode * Parent = NULL);

			//! Set Current Camera
			void SetCurrentCamera(ICameraSceneNode * Node);

			//! Get Current Camera
			ICameraSceneNode * GetCurrentCamera();

			//! Set Layer Control
			void SetLayerControl(u1 Enable);

			//! Get Layer Control
			u1 GetLayerControl();

			//! Swap Layers
			void SwapLayers(s32 Layer1,s32 Layer2);

			//! Return Scene Manager Render
			video::IRender * GetRender();

			//! Return Root
			ISceneNode * GetRoot();

			//! Get Node By Name
			ISceneNode * GetNodeByName(const jeStringd & NodeName);

			//! On Update
			void OnUpdate();

			//! On Render
			void OnRender();

			//! Register Node In Rendering Queue
			void RegisterNodeInRenderingQueue(ISceneNode * Node,RenderPassGroup Group,RenderPassGroupRights Rights);

			//! UnRegister Node From Rendering Queue
			void UnRegisterNodeFromRenderingQueue(ISceneNode * Node,RenderPassGroup Group);

			//! Render Queue Groups
			void RenderQueueGroups(u1 RenderAllGroups,RenderPassGroup Group);

			//! Render Queue Object
			void RenderQueueObject(u32 ObjectQueueIndex,RenderPassGroup Group);

			//! Get Count Of Objects In Queue Group
			u32 GetCountOfObjectsInQueueGroup(RenderPassGroup Group);

			//! Set Render Pass Group Rights
			void SetRenderPassGroupRights(RenderPassGroup Group,RenderPassGroupRights Rights = RPTR_AUTO);

			//! Add Compositor
			void AddCompositor(ICompositor * Compositor);

			//! Remove Compositor
			void RemoveCompositor(ICompositor * Compositor);

			//! Get Compositors List
			CompositorListType * GetCompositorList();

			//! Get Previous Compositor
			ICompositor * GetPreviousCompositor();

			//! Return Factory
			NodeFactoryType * GetNodeFactory();

			//! Return Animator Factory
			AnimatorFactoryType * GetAnimatorFactory();

			//! Return Compositor Factory
			CompositorFactoryType * GetCompositorFactory();

			//! Register Light
			void RegisterLight(ILightSceneNode * Light);

			//! UnRegister Light
			void UnRegisterLight(ILightSceneNode * Light);

			//! Get Light List
			LightListType * GetLightList();

			//! Serialize
			void Serialize(core::ISerializeStream * SerializeStream);

			//! Serialize
			void Serialize(ISceneNode * Node,core::ISerializeStream * SerializeStream);
		};
	}
}

#endif
